<!DOCTYPE html>
<html lang=zh>
<head>
  <meta charset="utf-8">
  <meta name=referrer content=never>
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no, minimal-ui">
  <meta name="renderer" content="webkit">
  <meta http-equiv="Cache-Control" content="no-transform" />
  <meta http-equiv="Cache-Control" content="no-siteapp" />
  <meta name="apple-mobile-web-app-capable" content="yes">
  <meta name="apple-mobile-web-app-status-bar-style" content="black">
  <meta name="format-detection" content="telephone=no,email=no,adress=no">
  <!-- Color theme for statusbar -->
  <meta name="theme-color" content="#000000" />
  <!-- 强制页面在当前窗口以独立页面显示,防止别人在框架里调用页面 -->
  <meta http-equiv="window-target" content="_top" />
  
  
  <title>对JAVA内存的一些理解 | JiSong‘s Blog</title>
  <meta name="description" content="2018-06-29 所学所理解内存中有以下模块：堆（heap），虚拟机栈（VM stack），本地方法栈（Native Method stack）,方法区（Method Area）,程序计数器（指令寄存器） 程序计数器1.在IDE上编译的Java代码运行时都会被转译成字节码。程序计数器的就是给编译好的字节码添加行号，这样这些字节码就以程序计数器的编号来作为调度时候的标识了。 2.在程序运行时，诸">
<meta name="keywords" content="JVM">
<meta property="og:type" content="article">
<meta property="og:title" content="对JAVA内存的一些理解">
<meta property="og:url" content="https://ji-song.gitee.io/blog/2018/06/29/对JAVA内存的一些理解/index.html">
<meta property="og:site_name" content="JiSong">
<meta property="og:description" content="2018-06-29 所学所理解内存中有以下模块：堆（heap），虚拟机栈（VM stack），本地方法栈（Native Method stack）,方法区（Method Area）,程序计数器（指令寄存器） 程序计数器1.在IDE上编译的Java代码运行时都会被转译成字节码。程序计数器的就是给编译好的字节码添加行号，这样这些字节码就以程序计数器的编号来作为调度时候的标识了。 2.在程序运行时，诸">
<meta property="og:locale" content="zh-CN">
<meta property="og:image" content="http://pba56k9nr.bkt.clouddn.com/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B.png">
<meta property="og:image" content="https://img-blog.csdn.net/20170228110737416">
<meta property="og:image" content="https://img-blog.csdn.net/20170228112128055">
<meta property="og:image" content="https://img-blog.csdn.net/20170228112156530">
<meta property="og:image" content="https://img-blog.csdn.net/20170228112243931">
<meta property="og:image" content="https://img-blog.csdn.net/20170228120023427">
<meta property="og:updated_time" content="2018-07-03T08:57:51.000Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="对JAVA内存的一些理解">
<meta name="twitter:description" content="2018-06-29 所学所理解内存中有以下模块：堆（heap），虚拟机栈（VM stack），本地方法栈（Native Method stack）,方法区（Method Area）,程序计数器（指令寄存器） 程序计数器1.在IDE上编译的Java代码运行时都会被转译成字节码。程序计数器的就是给编译好的字节码添加行号，这样这些字节码就以程序计数器的编号来作为调度时候的标识了。 2.在程序运行时，诸">
<meta name="twitter:image" content="http://pba56k9nr.bkt.clouddn.com/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B.png">
  <!-- Canonical links -->
  <link rel="canonical" href="https://ji-song.gitee.io/blog/2018/06/29/对JAVA内存的一些理解/index.html">
  
    <link rel="alternate" href="/atom.xml" title="JiSong" type="application/atom+xml">
  
  
    <link rel="icon" href="/blog/favicon.png" type="image/x-icon">
  
  <!-- font-awesome CSS -->
  <!-- <link href="https://cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> -->
  <link rel="stylesheet" href="/blog/css/style.css">
  
    
    

</head>


<body class="main-center theme-green" itemscope itemtype="http://schema.org/WebPage">
  <header class="header" itemscope itemtype="http://schema.org/WPHeader">
  <div class="slimContent">
    <div class="navbar-header">
      
      
      <div class="profile-block text-center">
        <a id="avatar" href="https://gitee.com/ji-song" target="_blank">
          <img class="img-circle img-rotate" src="/blog/images/avatar.jpeg" width="200" height="200">
        </a>
        <h2 id="name" class="hidden-xs hidden-sm">JiSong</h2>
        <h3 id="title" class="hidden-xs hidden-sm hidden-md">Java Coder</h3>
        <small id="location" class="text-muted hidden-xs hidden-sm"><i class="icon icon-map-marker"></i> HangZhou, China</small>
      </div>
      
      <div class="search" id="search-form-wrap">

    <form class="search-form sidebar-form">
        <div class="input-group">
            <input type="text" class="search-form-input form-control" placeholder="搜索" />
            <span class="input-group-btn">
                <button type="submit" class="search-form-submit btn btn-flat" onclick="return false;"><i class="icon icon-search"></i></button>
            </span>
        </div>
    </form>
    <div class="ins-search">
  <div class="ins-search-mask"></div>
  <div class="ins-search-container">
    <div class="ins-input-wrapper">
      <input type="text" class="ins-search-input" placeholder="想要查找什么..." x-webkit-speech />
      <button type="button" class="close ins-close ins-selectable" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
    </div>
    <div class="ins-section-wrapper">
      <div class="ins-section-container"></div>
    </div>
  </div>
</div>


</div>
      <button class="navbar-toggle collapsed" type="button" data-toggle="collapse" data-target="#main-navbar" aria-controls="main-navbar" aria-expanded="false">
        <span class="sr-only">Toggle navigation</span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
        <span class="icon-bar"></span>
      </button>
    </div>
    <nav id="main-navbar" class="collapse navbar-collapse" itemscope itemtype="http://schema.org/SiteNavigationElement" role="navigation">
      <ul class="nav navbar-nav main-nav">
        
        
        
        <li class="menu-item menu-item-home">
          <a href="/blog/.">
            
            <i class="icon icon-home-fill"></i>
            
            <span class="menu-title">首页</span>
          </a>
        </li>
        
        
        
        <li class="menu-item menu-item-archives">
          <a href="/blog/archives">
            
            <i class="icon icon-archives-fill"></i>
            
            <span class="menu-title">所有文章</span>
          </a>
        </li>
        
        
        
        <li class="menu-item menu-item-categories">
          <a href="/blog/categories">
            
            <i class="icon icon-folder"></i>
            
            <span class="menu-title">分类</span>
          </a>
        </li>
        
        
        
        <li class="menu-item menu-item-about">
          <a href="/blog/about">
            
            <i class="icon icon-cup-fill"></i>
            
            <span class="menu-title">关于</span>
          </a>
        </li>
        
      </ul>
      
	
    <ul class="social-links">
    	
        <li><a href="https://gitee.com/ji-song" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
    </ul>

    </nav>
  </div>
</header>

  
    <aside class="sidebar" itemscope itemtype="http://schema.org/WPSideBar">
  <div class="slimContent">
    
      <div class="widget">
    <h3 class="widget-title">了解一下</h3>
    <div class="widget-body">
        <div id="board">
            <div class="content">
                <p>欢迎交流与分享经验!来来来</p>
            </div>
        </div>
    </div>
</div>

    
      
  <div class="widget">
    <h3 class="widget-title">分类</h3>
    <div class="widget-body">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/blog/categories/技能/">技能</a><span class="category-list-count">19</span></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/生活/">生活</a><span class="category-list-count">2</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">标签</h3>
    <div class="widget-body">
      <ul class="tag-list"><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/AOP/">AOP</a><span class="tag-list-count">7</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/DB/">DB</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/JDK/">JDK</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/JVM/">JVM</a><span class="tag-list-count">3</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/Kotlin/">Kotlin</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/Log/">Log</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/MVC/">MVC</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/Spring/">Spring</a><span class="tag-list-count">10</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/job/">job</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/kotlin/">kotlin</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/linux/">linux</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/plan/">plan</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/sublime/">sublime</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/事务/">事务</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/坑记/">坑记</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/并发/">并发</a><span class="tag-list-count">1</span></li><li class="tag-list-item"><a class="tag-list-link" href="/blog/tags/集合/">集合</a><span class="tag-list-count">2</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">标签云</h3>
    <div class="widget-body tagcloud">
      <a href="/blog/tags/AOP/" style="font-size: 13.75px;">AOP</a> <a href="/blog/tags/DB/" style="font-size: 13px;">DB</a> <a href="/blog/tags/JDK/" style="font-size: 13.5px;">JDK</a> <a href="/blog/tags/JVM/" style="font-size: 13.5px;">JVM</a> <a href="/blog/tags/Kotlin/" style="font-size: 13px;">Kotlin</a> <a href="/blog/tags/Log/" style="font-size: 13px;">Log</a> <a href="/blog/tags/MVC/" style="font-size: 13px;">MVC</a> <a href="/blog/tags/Spring/" style="font-size: 14px;">Spring</a> <a href="/blog/tags/job/" style="font-size: 13px;">job</a> <a href="/blog/tags/kotlin/" style="font-size: 13px;">kotlin</a> <a href="/blog/tags/linux/" style="font-size: 13px;">linux</a> <a href="/blog/tags/plan/" style="font-size: 13px;">plan</a> <a href="/blog/tags/sublime/" style="font-size: 13px;">sublime</a> <a href="/blog/tags/事务/" style="font-size: 13px;">事务</a> <a href="/blog/tags/坑记/" style="font-size: 13px;">坑记</a> <a href="/blog/tags/并发/" style="font-size: 13px;">并发</a> <a href="/blog/tags/集合/" style="font-size: 13.25px;">集合</a>
    </div>
  </div>

    
      
  <div class="widget">
    <h3 class="widget-title">所有文章</h3>
    <div class="widget-body">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2018/08/">八月 2018</a><span class="archive-list-count">2</span></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2018/07/">七月 2018</a><span class="archive-list-count">12</span></li><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2018/06/">六月 2018</a><span class="archive-list-count">7</span></li></ul>
    </div>
  </div>


    
      
  <div class="widget">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget-body">
      <ul class="recent-post-list list-unstyled no-thumbnail">
        
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/blog/categories/技能/">技能</a>
              </p>
              <p class="item-title">
                <a href="/blog/2018/08/08/JAVA对象的两种访问定位方式/" class="title">JAVA对象的两种访问定位方式</a>
              </p>
              <p class="item-date">
                <time datetime="2018-08-08T06:41:32.000Z" itemprop="datePublished">2018年08月08日</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/blog/categories/技能/">技能</a>
              </p>
              <p class="item-title">
                <a href="/blog/2018/08/07/spring-mvc源码阅读-DispatcherServlet/" class="title">spring mvc源码阅读 - DispatcherServlet</a>
              </p>
              <p class="item-date">
                <time datetime="2018-08-07T01:57:38.000Z" itemprop="datePublished">2018年08月07日</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/blog/categories/技能/">技能</a>
              </p>
              <p class="item-title">
                <a href="/blog/2018/07/26/ACID/" class="title">ACID</a>
              </p>
              <p class="item-date">
                <time datetime="2018-07-26T14:24:03.000Z" itemprop="datePublished">2018年07月26日</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/blog/categories/技能/">技能</a>
              </p>
              <p class="item-title">
                <a href="/blog/2018/07/12/Kotlin-的异常/" class="title">Kotlin 的异常</a>
              </p>
              <p class="item-date">
                <time datetime="2018-07-12T13:42:03.000Z" itemprop="datePublished">2018年07月12日</time>
              </p>
            </div>
          </li>
          
          <li>
            
            <div class="item-inner">
              <p class="item-category">
                <a class="category-link" href="/blog/categories/技能/">技能</a>
              </p>
              <p class="item-title">
                <a href="/blog/2018/07/12/Spring-AOP-玩一下异常的流程/" class="title">Spring AOP 玩一下异常的流程</a>
              </p>
              <p class="item-date">
                <time datetime="2018-07-12T13:39:07.000Z" itemprop="datePublished">2018年07月12日</time>
              </p>
            </div>
          </li>
          
      </ul>
    </div>
  </div>
  

    
  </div>
</aside>

  
  
<main class="main" role="main">
  <div class="content">
  <article id="post-对JAVA内存的一些理解" class="article article-type-post" itemscope itemtype="http://schema.org/BlogPosting">
    
    <div class="article-header">
      
        
  
    <h1 class="article-title" itemprop="name">
      对JAVA内存的一些理解
    </h1>
  

      
      <div class="article-meta">
        <span class="article-date">
    <i class="icon icon-calendar-check"></i>
	<a href="/blog/2018/06/29/对JAVA内存的一些理解/" class="article-date">
	  <time datetime="2018-06-29T07:57:54.000Z" itemprop="datePublished">2018年06月29日</time>
	</a>
</span>
        
  <span class="article-category">
    <i class="icon icon-folder"></i>
    <a class="article-category-link" href="/blog/categories/技能/">技能</a>
  </span>

        
  <span class="article-tag">
    <i class="icon icon-tags"></i>
	<a class="article-tag-link" href="/blog/tags/JVM/">JVM</a>
  </span>


        

        <span class="post-comment"><i class="icon icon-comment"></i> <a href="/blog/2018/06/29/对JAVA内存的一些理解/#comments" class="article-comment-link">评论</a></span>
        
      </div>
    </div>
    <div class="article-entry markdown-body" itemprop="articleBody">
      
        <h2 id="2018-06-29-所学所理解"><a href="#2018-06-29-所学所理解" class="headerlink" title="2018-06-29 所学所理解"></a>2018-06-29 所学所理解</h2><p>内存中有以下模块：<br>堆（heap），虚拟机栈（VM stack），本地方法栈（Native Method stack）,方法区（Method Area）,程序计数器（指令寄存器）<br><img src="http://pba56k9nr.bkt.clouddn.com/%E5%86%85%E5%AD%98%E6%A8%A1%E5%9E%8B.png" alt="内存模型"></p>
<h2 id="程序计数器"><a href="#程序计数器" class="headerlink" title="程序计数器"></a>程序计数器</h2><p>1.在IDE上编译的Java代码运行时都会被转译成字节码。程序计数器的就是给编译好的字节码添加行号，这样这些字节码就以程序计数器的编号来作为调度时候的标识了。</p>
<p>2.在程序运行时，诸如循环，跳转，异常处理这些功能都必须依赖于字节码来完。</p>
<p>3.由于Java 虚拟机的多线程是通过线程轮流切换并分配处理器执行时间的方式来实现的，在任何一个确定的时刻，一个处理器（对于多核处理器来说是一个内核）只会执行一条线程中的指令。因此，为了线程切换后能恢复到正确的执行位置，每条线程都需要有一个独立的程序计数器，各条线程之间的计数器互不影响，独立存储，我们称这类内存区域为“线程私有”的内存。</p>
<p>更愿意叫它《指令寄存器》，是存储CPU要执行的下一条指令的位置。</p>
<h2 id="虚拟机栈"><a href="#虚拟机栈" class="headerlink" title="虚拟机栈"></a>虚拟机栈</h2><p>每个线程有一个私有的栈，随着线程的创建而创建，栈里面存储着“栈帧”，每个方法会创建一个栈帧，栈帧中存放了局部变量表（基本数据类型和对象引用），操作数栈，方法出口等信息。</p>
<p>栈的大小可以固定，也可以扩展。</p>
<p>当栈调用深度大于JVM所允许的范围，会抛出StackOverflowError的错误，不过，这个深度范围不是一个固定值。</p>
<p>当申请不到足够的内存空间时，会抛出OutOfMemeryError，</p>
<p>（StackOverflowError和OutOfMemeryError都不属于Exception 子类，所以在catch时，捕获的是Throwable，而不是Exception）</p>
<h2 id="本地方法栈"><a href="#本地方法栈" class="headerlink" title="本地方法栈"></a>本地方法栈</h2><p>JVM调用的一些本地方法，比如C函数：<a href="https://www.cnblogs.com/wade-luffy/p/5813747.html" target="_blank" rel="noopener">JVM的本地方法栈</a></p>
<h2 id="方法区"><a href="#方法区" class="headerlink" title="方法区"></a>方法区</h2><p>线程共享的区域</p>
<p>对于每个被加载的类，在方法区中保存以下信息</p>
<ol>
<li><p>类型信息</p>
<ol>
<li>类的名称在java源文件和JVM中都以完整类名出现，有效类名包括类路径和类名。<br>源文件的有效类名为：java.lang.Object (以.分隔)<br>类文件的有效类名为：java/lang/Object（以/分隔）</li>
<li>父类的完整类名</li>
<li>直接父接口的完整类名</li>
<li>类标识：class 或 interface</li>
<li>类的访问权限：public / private / default / abstract / final / static</li>
</ol>
</li>
<li><p>类的常量池（JDK1.8）<br> 该类所用到的常量的<strong>有序集合</strong></p>
<ol>
<li>直接常量，如字符串，整数，浮点数及其他基本数据类型。</li>
<li>对其他类型，字段，方法的引用。</li>
</ol>
</li>
<li>字段信息<ol>
<li>修饰符 （public , protect , private , default）</li>
<li>类型 </li>
<li>名称</li>
</ol>
</li>
<li><p>方法信息<br> 包含类的所有方法，每个方法都有以下信息</p>
<ol>
<li>修饰符</li>
<li>返回类型</li>
<li>名称</li>
<li>参数个数，类型，顺序等</li>
<li>方法体（字节码）</li>
<li>异常表</li>
<li>操作数栈和该方法在栈帧中的局部变量区大小</li>
</ol>
</li>
<li><p>类变量-静态变量<br> 不用实例化对象，也能访问的变量</p>
</li>
<li>指向类加载器的引用<br> 类加载器动态链接时会用到。</li>
<li>指向Class实例的引用<br>类加载的过程中，虚拟机会创建该类型的Class实例，方法区中必须保存对该对象的引用。通过Class.forName(String className)来查找获得该实例的引用，然后创建该类的对象。</li>
<li>方法表<br>为了提高访问效率，JVM可能会对每个装载的非抽象类，都创建一个数组，数组的每个元素是实例可能调用的方法的直接引用，包括父类中继承过来的方法。这个表在抽象类或者接口中是没有的。</li>
<li>Runtime Constant Pool(运行时常量池)<br>用于存放编译器生成的各种字面常量和符号引用，这部分内容被类加载后进入方法区的运行时常量池中存放。</li>
</ol>
<p>可以在运行期间将新的常量放入池中（如String类的intern()方法）</p>
<blockquote>
<p>运行时常量池是把Class文件常量池加载进来，每个类有一个独立的。刚开始时运行的时候常量池里的链接都是符号链接（只用名字没有实体），跟在Class文件里的一样；边运行边把常量转换成直接链接。例如说要Class A调用Foo.bar()方法，A.class文件里就会有对该方法的Method ref常量，是个符号链接（只有名字没有实体），加载到运行时常量池也还是一样是符号链接，等真的要调用该方法的时候该常量就会被resolve为一个直接链接（直接指向要调用的方法的实体）</p>
</blockquote>
<p>参考与借鉴：<a href="https://blog.csdn.net/huangfan322/article/details/53220169" target="_blank" rel="noopener">JAVA虚拟机方法区介绍</a></p>
<h2 id="heap（堆）"><a href="#heap（堆）" class="headerlink" title="heap（堆）"></a>heap（堆）</h2><p>线程共享的区域</p>
<p>heap是JVM内存管理中最大的一块区域，此区域唯一目的就是存放对象的实例，所有对象实例和数组都要在heap上分配内存。</p>
<p>它是GC的主要管理区域。</p>
<p>heap和stack是有关联的。stack存储的是heap对象的引用地址。</p>
<p>对于heap和stack比较好理解的好文 ：</p>
<ul>
<li><a href="https://www.cnblogs.com/SaraMoring/p/5687466.html" target="_blank" rel="noopener">Java内存分配之堆、栈和常量池</a></li>
<li><a href="https://blog.csdn.net/cutesource/article/details/8244250" target="_blank" rel="noopener">从几个sample来学习Java堆，方法区，Java栈和本地方法栈</a></li>
</ul>
<hr>
<p>以下转自：<a href="https://blog.csdn.net/universe_ant/article/details/58585854" target="_blank" rel="noopener">Java8内存模型</a></p>
<h2 id="二、PermGen-永久代"><a href="#二、PermGen-永久代" class="headerlink" title="二、PermGen(永久代)"></a>二、PermGen(永久代)</h2><p>绝大部分Java程序员应该都见过“java.lang.OutOfMemoryError: PremGen space”异常。这里的“PermGen space”其实指的就是方法区。不过方法区和“PermGen space”又有着本质的区别。前者是JVM的规范，而后者则是JVM规范的一种实现，并且只有HotSpot才有“PermGen space”，而对于其他类型的虚拟机，如JRockit(Oracle)、J9(IBM)并没有“PermGen space”。由于方法区主要存储类的相关信息，所以对于动态生成类的情况比较容易出现永久代的内存溢出。最典型的场景就是，在JSP页面比较多的情况，容易出现永久代内存溢出。我们现在通过动态生成类来模拟“PermGen space”的内存溢出：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">package com.paddx.test.memory;</span><br><span class="line"> </span><br><span class="line">import java.io.File;</span><br><span class="line">import java.net.URL;</span><br><span class="line">import java.net.URLClassLoader;</span><br><span class="line">import java.util.ArrayList;</span><br><span class="line">import java.util.List;</span><br><span class="line"> </span><br><span class="line">public class PermGenOomMock &#123;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		URL url = null;</span><br><span class="line">		List&lt;ClassLoader&gt; classLoaderList = new ArrayList&lt;ClassLoader&gt;();</span><br><span class="line">		try &#123;</span><br><span class="line">			url = new File(&quot;/tmp&quot;).toURI().toURL();</span><br><span class="line">			URL[] urls = &#123;url&#125;;</span><br><span class="line">			while(true) &#123;</span><br><span class="line">				ClassLoader loader = new URLClassLoader(urls);</span><br><span class="line">				classLoaderList.add(loader);</span><br><span class="line">				loader.loadClass(&quot;com.paddx.test.memory.Test&quot;);</span><br><span class="line">			&#125;</span><br><span class="line">		&#125;catch(Exception e) &#123;</span><br><span class="line">			e.printStackTrace();</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">package com.paddx.test.memory;</span><br><span class="line"> </span><br><span class="line">public class Test &#123;&#125;</span><br></pre></td></tr></table></figure></p>
<p>运行结果如下：<br><img src="https://img-blog.csdn.net/20170228110737416" alt=""></p>
<p>本例中使用的JDK版本是1.7，指定的PermGen区的大小为8M。通过每次生成不同URLClassLoader对象加载Test类，从而生成不同的类对象，这样就能看到我们熟悉的“java.lang.OutOfMemoryError: PermGen space”异常了。这里之所以采用JDK 1.7，是因为在JDK 1.8中，HotSpot已经没有“PermGen space”这个区间了，取而代之是一个叫做Metaspace(元空间)的东西。下面我们就来看看Metaspace与PermGen space的区别。</p>
<h2 id="三、Metaspace-元空间"><a href="#三、Metaspace-元空间" class="headerlink" title="三、Metaspace(元空间)"></a>三、Metaspace(元空间)</h2><p>其实，移除永久代的工作从JDK 1.7就开始了。JDK 1.7中，存储在永久代的部分数据就已经转移到Java Heap或者Native Heap。但永久代仍存在于JDK 1.7中，并没有完全移除，譬如符号引用(Symbols)转移到了native heap；字面量(interned strings)转移到了Java heap；类的静态变量(class statics)转移到了Java heap。我们可以通过一段程序来比较JDK 1.6、JDK 1.7与JDK 1.8的区别，以字符串常量为例：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">package com.paddx.test.memory;</span><br><span class="line"> </span><br><span class="line">import java.util.ArrayList;</span><br><span class="line">import java.util.List;</span><br><span class="line"> </span><br><span class="line">public class StringOomMock &#123;</span><br><span class="line">	static String base = &quot;string&quot;;</span><br><span class="line">	public static void main(String[] args) &#123;</span><br><span class="line">		List&lt;String&gt; list = new ArrayList&lt;String&gt;();</span><br><span class="line">		for (int i = 0; i &lt; Integer.MAX_VALUE; i++) &#123;</span><br><span class="line">			String str = base + base;</span><br><span class="line">			base = str;</span><br><span class="line">			list.add(str.intern());</span><br><span class="line">		&#125;</span><br><span class="line">	&#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></p>
<p>这段程序以2的指数级不断的生成新的字符串，这样可以比较快速的消耗内存。我们通过JDK 1.6、JDK 1.7和JDK 1.8分别运行：<br>JDK 1.6的运行结果：<br><img src="https://img-blog.csdn.net/20170228112128055" alt=""></p>
<p>JDK 1.7的运行结果：<br><img src="https://img-blog.csdn.net/20170228112156530" alt=""></p>
<p>JDK 1.8的运行结果：<br><img src="https://img-blog.csdn.net/20170228112243931" alt=""></p>
<p>从上述结果可以看出，JDK 1.6下，会出现“PermGen space”的内存溢出，而在JDK 1.7和JDK 1.8中，会出现堆内存溢出，并且JDK 1.8中参数PermSize和MaxPermSize已经失效。因此，可以大致验证JDK 1.7和JDK 1.8中将字符串常量由永久代转移到堆中，并且JDK 1.8中已经不存在永久代的结论。现在我们来看一看元空间到底是一个什么东西？</p>
<p><strong>JDK1.8</strong>对JVM架构的改造<strong>将类元数据放到本地内存</strong>中，另外，<strong>将常量池和静态变量放到Java堆</strong>里。HotSpot VM将会为类的元数据明确分配和释放本地内存。在这种架构下，类元信息就突破了原来-XX:MaxPermSize的限制，现在可以使用更多的本地内存。这样就从一定程度上解决了原来在运行时生成大量类造成经常Full GC问题，如运行时使用反射、代理等。所以升级以后Java堆空间可能会增加。</p>
<p>元空间的本质和永久代类似，都是对JVM规范中方法区的实现。不过元空间与永久代之间的最大区别在于：<strong>元空间并不在虚拟机中，而是使用本地内存</strong>。因此，默认情况下，元空间的大小仅受本地内存限制，但可以通过以下参数指定元空间的大小：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">-XX:MetaspaceSize，初始空间大小，达到该值就会触发垃圾收集进行类型卸载，同时GC会对改值进行调整：如果释放了大量的空间，就适当降低该值；如果释放了很少的空间，那么在不超过MaxMetaspaceSize时，适当提高该值。</span><br><span class="line"></span><br><span class="line">-XX:MaxMetaspaceSize，最大空间，默认是没有限制的。</span><br></pre></td></tr></table></figure></p>
<p>除了上面的两个指定大小的选项外，还有两个与GC相关的属性：<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">-XX:MinMetaspaceFreeRatio，在GC之后，最小的Metaspace剩余空间容量的百分比，减少为分配空间所导致的垃圾收集。</span><br><span class="line"></span><br><span class="line">-XX:MaxMetaspaceFreeRatio，在GC之后，最大的Metaspace剩余空间容量的百分比，减少为释放空间所导致的垃圾收集。</span><br></pre></td></tr></table></figure></p>
<p>现在我们在JDK 1.8重新运行一下上面第二部分(PermGen(永久代))的代码，不过这次不再指定PermSize和MaxPermSize。而是制定MetaspaceSize和MaxMetaspaceSize的大小。输出结果如下：<br><img src="https://img-blog.csdn.net/20170228120023427" alt=""></p>
<p>从输出结果，我们可以看出，这次不再出现永久代溢出，而是出现元空间的溢出。</p>
<p>四、总结<br>通过上面的分析，大家应该大致了解了JVM的内存划分，也清楚了JDK 1.8中永久代向元空间的转换。不过大家应该有一个疑问，就是为什么要做这个转换？以下为大家总结几点原因：</p>
<ul>
<li>字符串在永久代中，容易出现性能问题和内存溢出。</li>
<li>类及方法的信息等比较难确定大小，因此对于永久代的大小指定比较困难，太小容易出现永久代溢出，太大则容易出现老年代溢出。</li>
<li>永久代会为GC带来不必要的复杂度，并且回收效率偏低。</li>
<li>Oracle可能会将HotSpot与JRockit合二为一。</li>
</ul>

      
    </div>
    <div class="article-footer">
      <blockquote class="mt-2x">
  <ul class="post-copyright list-unstyled">
    
    <li class="post-copyright-link hidden-xs">
      <strong>本文链接：</strong>
      <a href="https://ji-song.gitee.io/blog/2018/06/29/对JAVA内存的一些理解/" title="对JAVA内存的一些理解" target="_blank" rel="external">https://ji-song.gitee.io/blog/2018/06/29/对JAVA内存的一些理解/</a>
    </li>
    
    <li class="post-copyright-license">
      <strong>版权声明： </strong> 本博客所有文章除特别声明外，均采用 <a href="http://creativecommons.org/licenses/by/4.0/deed.zh" target="_blank" rel="external">CC BY 4.0 CN协议</a> 许可协议。转载请注明出处！
    </li>
  </ul>
</blockquote>


<div class="panel panel-default panel-badger">
  <div class="panel-body">
    <figure class="media">
      <div class="media-left">
        <a href="https://gitee.com/ji-song" target="_blank" class="img-burn thumb-sm visible-lg">
          <img src="/blog/images/avatar.jpeg" class="img-rounded w-full" alt="">
        </a>
      </div>
      <div class="media-body">
        <h3 class="media-heading"><a href="https://gitee.com/ji-song" target="_blank"><span class="text-dark">JiSong</span><small class="ml-1x">Java Coder</small></a></h3>
        <div>个人简介。</div>
      </div>
    </figure>
  </div>
</div>


    </div>
  </article>
  
    
  <section id="comments">
  	
  </section>


  
</div>

  <nav class="bar bar-footer clearfix" data-stick-bottom>
  <div class="bar-inner">
  
  <ul class="pager pull-left">
    
    <li class="prev">
      <a href="/blog/2018/06/29/JAVA内存-程序计数器/" title="JAVA内存-程序计数器"><i class="icon icon-angle-left" aria-hidden="true"></i><span>&nbsp;&nbsp;上一篇</span></a>
    </li>
    
    
    <li class="next">
      <a href="/blog/2018/06/28/java多线程：CAS/" title="java多线程：CAS"><span>下一篇&nbsp;&nbsp;</span><i class="icon icon-angle-right" aria-hidden="true"></i></a>
    </li>
    
    
  </ul>
  
  
  <!-- Button trigger modal -->
  <button type="button" class="btn btn-fancy btn-donate pop-onhover bg-gradient-warning" data-toggle="modal" data-target="#donateModal"><span>赏</span></button>
  <!-- <div class="wave-icon wave-icon-danger btn-donate" data-toggle="modal" data-target="#donateModal">
    <div class="wave-circle"><span class="icon"><i class="icon icon-bill"></i></span></div>
  </div> -->
  
  
  <div class="bar-right">
    
    <div class="share-component" data-sites="weibo,qq,wechat,facebook,twitter" data-mobile-sites="weibo,qq,qzone"></div>
    
  </div>
  </div>
</nav>
  
<!-- Modal -->
<div class="modal modal-center modal-small modal-xs-full fade" id="donateModal" tabindex="-1" role="dialog">
  <div class="modal-dialog" role="document">
    <div class="modal-content donate">
      <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
      <div class="modal-body">
        <div class="donate-box">
          <div class="donate-head">
            <p>感谢您的支持，我会继续努力的!</p>
          </div>
          <div class="tab-content">
            <div role="tabpanel" class="tab-pane fade active in" id="alipay">
              <div class="donate-payimg">
                <img src="/blog/images/donate/alipayimg.jpg" alt="扫码支持" title="扫一扫" />
              </div>
              <p class="text-muted mv">扫码打赏，你说多少就多少</p>
              <p class="text-grey">打开支付宝扫一扫，即可进行扫码打赏哦</p>
            </div>
            <div role="tabpanel" class="tab-pane fade" id="wechatpay">
              <div class="donate-payimg">
                <img src="/blog/images/donate/wechatpayimg.jpg" alt="扫码支持" title="扫一扫" />
              </div>
              <p class="text-muted mv">扫码打赏，你说多少就多少</p>
              <p class="text-grey">打开微信扫一扫，即可进行扫码打赏哦</p>
            </div>
          </div>
          <div class="donate-footer">
            <ul class="nav nav-tabs nav-justified" role="tablist">
              <li role="presentation" class="active">
                <a href="#alipay" id="alipay-tab" role="tab" data-toggle="tab" aria-controls="alipay" aria-expanded="true"><i class="icon icon-alipay"></i> 支付宝</a>
              </li>
              <li role="presentation" class="">
                <a href="#wechatpay" role="tab" id="wechatpay-tab" data-toggle="tab" aria-controls="wechatpay" aria-expanded="false"><i class="icon icon-wepay"></i> 微信支付</a>
              </li>
            </ul>
          </div>
        </div>
      </div>
    </div>
  </div>
</div>



</main>

  <footer class="footer" itemscope itemtype="http://schema.org/WPFooter">
	
	
    <ul class="social-links">
    	
        <li><a href="https://gitee.com/ji-song" target="_blank" title="Github" data-toggle=tooltip data-placement=top><i class="icon icon-github"></i></a></li>
        
    </ul>

    <div class="copyright">
    	
        <div class="publishby">
        	Theme by <a href="https://github.com/cofess" target="_blank"> cofess </a>base on <a href="https://github.com/cofess/hexo-theme-pure" target="_blank">pure</a>.
        </div>
    </div>
</footer>
  <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<script>
window.jQuery || document.write('<script src="js/jquery.min.js"><\/script>')
</script>
<script src="/blog/js/plugin.min.js"></script>
<script src="/blog/js/application.js"></script>
  
    
    
    
        <script>
(function (window) {
    var INSIGHT_CONFIG = {
        TRANSLATION: {
            POSTS: '文章',
            PAGES: '页面',
            CATEGORIES: '分类',
            TAGS: '标签',
            UNTITLED: '(未命名)',
        },
        ROOT_URL: '/blog/',
        CONTENT_URL: '/blog/content.json',
    };
    window.INSIGHT_CONFIG = INSIGHT_CONFIG;
})(window);
</script>
<script src="/blog/js/insight.js"></script>
    
    
    
        


    
    
        
    
    



</body>
</html>